﻿using System;
using System.Collections.Generic;
using System.Text;
using Statistics;

using ELW.Library.Math;
using ELW.Library.Math.Exceptions;
using ELW.Library.Math.Expressions;
using ELW.Library.Math.Tools;

namespace Simulator
{
    /// <summary>
    /// Источник сущностей
    /// </summary>
    [Serializable]
    public class Source: Block
    {
        /// <summary>
        /// Единицы измерения времени
        /// </summary>
        public TimeUnits SimulationTimeUnits { get; set; }

        private string Qstr, Tstr, Cstr;

        //скомпилированные выражения для парсера
        public CompiledExpression TimeCompiledString;
        public CompiledExpression QualityCompiledString;
        public CompiledExpression ComplexityCompiledString;

        public string QualityString
        {
            get
            { return Qstr; }
            set
            {
                Qstr = value;
                PreparedExpression preparedExpression = ToolsHelper.Parser.Parse(Qstr);
                QualityCompiledString = ToolsHelper.Compiler.Compile(preparedExpression);
            }
        }
        public string TimeString
        {
            get
            { return Tstr; }
            set
            {
                Tstr = value;
                PreparedExpression preparedExpression = ToolsHelper.Parser.Parse(Tstr);
                TimeCompiledString = ToolsHelper.Compiler.Compile(preparedExpression);
            }
        }
        public string ComplexityString
        {
            get
            { return Cstr; }
            set
            {
                Cstr = value;
                PreparedExpression preparedExpression = ToolsHelper.Parser.Parse(Cstr);
                ComplexityCompiledString = ToolsHelper.Compiler.Compile(preparedExpression);
            }
        }

        private int entityCounter = 0;

        public Source()
        {
            QualityString = "0";
            TimeString = "0";
            ComplexityString = "0";
            SimulationTimeUnits = TimeUnits.seconds;
        }

        /// <summary>
        /// Сгенерировать сущность
        /// </summary>
        /// <returns>Сущность</returns>
        public Entity GenerateEntity()
        {
            Entity e = new Entity();            
            e.Index = entityCounter++;
            e.OwnerBlock = this;

            double time = ToolsHelper.Calculator.Calculate(TimeCompiledString, new List<VariableValue>());
            //переведем time в секунды
            double d = 1;//множитель
            switch (SimulationTimeUnits)
            {
                case TimeUnits.days:
                    d = 3600 * 8;//секунд в рабочем дне (8 ч)
                    break;
                case TimeUnits.hours:
                    d = 3600;
                    break;
                case TimeUnits.minutes:
                    d = 60;
                    break;
            }
            e.TimeRemained = d * time;
            e.Quality = ToolsHelper.Calculator.Calculate(QualityCompiledString, new List<VariableValue>());
            e.Complexity = ToolsHelper.Calculator.Calculate(QualityCompiledString, new List<VariableValue>());

            return e;
        }
        /// <summary>
        /// Передать сущность дальше
        /// </summary>
        /// <param name="e">Сущность, которую передаем</param>
        public void TransferEntity(ref Entity e)//передать сущность дальше
        {
            //передадим сущность далее
            Next.PutEntity(ref e);
        }
        /// <summary>
        /// Метод-заглушка
        /// </summary>
        /// <param name="e"></param>
        public override void PutEntity(ref Entity e)
        {
            return;
        }

        public override void ClearEntities()
        {
            entityCounter = 0;
        }
    }
}
